<?php

namespace app\storeapi\model;

/**
 * 商品模型
 * Class Goods
 * @package app\store\model
 */
class Goods extends Base
{

    protected $name = 'goods';

    protected $append = ['goods_sales'];
    /**
     * 商品组件：获取商品列表
     * @param $user
     * @param $item
     * @return array
     * @throws \think\exception\DbException
     */
    public function getGoodsList($param)
    {

        // 数据来源：自动
        $goodsList = $this->goodsList($param);
        if ($goodsList->isEmpty()) return [];
        // 格式化商品列表
        $data = [];
        foreach ($goodsList as $goods) {
            $data[] = [
                'goods_id' => $goods['goods_id'],//商品id
                'goods_name' => $goods['goods_name'],//商品名称
                'goods_image' => $goods['image'][0]['file_path'],//商品图片
                'goods_price' => $goods['sku'][0]['goods_price'],//商品价格
                //'line_price' => $goods['sku'][0]['line_price'],//划线价
                'goods_stock_num' => $goods['sku'][0]['stock_num'],//商品库存
                'goods_sales' => $goods['goods_sales'],//商品销量
                'goods_status' => $goods['goods_status'],//商品状态
                'spec_type' => $goods['spec_type'],//商品规格
            ];
        }
        return $data;
    }


    /**
     * 商品详情
     * @param array $data
     * @return bool
     * @throws \think\exception\PDOException
     */
    public function detail($param){

        /* @var $model self */
        $model = $this->with([
            'category',
            'image.file',
            'sku.image',
            'spec_rel.spec',
            'delivery',
        ])->where(['goods_id'=>$param['goods_id'],'wxapp_id'=>$param['wxapp_id']])
            ->find();

        if (empty($model)) {
            return [];
        }
        // 整理商品数据并返回
        return $model->setGoodsListData($model, false);
    }

    /*
     * 获取商品详情
     */
    public function getInfo($param){
        $model =$this->where(['goods_id'=>$param['goods_id'],'wxapp_id'=>$param['wxapp_id']])
            ->find();
        if(empty($model)){
            return [];
        }
        return $model;
    }
    /**
     * 获取商品图片，title
     */
    public function getGoodInfo($param){
        $model = $this->where(['goods_id'=>$param['goods_id'],'wxapp_id'=>$param['wxapp_id']])->with([
            'image.file',
        ])->find();
        if (empty($model)) {
            return [];
        }
        // 整理商品数据并返回
        return $model;
    }
    /**
     * 添加商品
     * @param array $param
     * @return bool
     * @throws \think\exception\PDOException
     */
    public function add($param)
    {
        // 开启事务
        $this->startTrans();
        try {
            // 添加商品
            $this->allowField(true)->save($param);
            // 商品规格
            $this->addGoodsSpec($param);
            // 商品图片
            $this->addGoodsImages($param['images'],$param['wxapp_id']);
            $this->commit();
            return true;
        } catch (\Exception $e) {
            $this->error = $e->getMessage();
            $this->rollback();
            return false;
        }
    }

    /**
     * 编辑商品
     * @param $data
     * @return bool|mixed
     */
    public function edit($param)
    {
        return $this->transaction(function () use ($param) {
            // 保存商品
            $this->allowField(true)->isUpdate(true,['goods_id'=>$param['goods_id']])->save($param);
            // 商品规格
            $this->addGoodsSpec($param, true);
            // 商品图片
            $this->addGoodsImages($param['images']);
            return true;
        });
    }


    /**
     * 商品列表
     * @param array $data
     * @return bool
     * @throws \think\exception\PDOException
     */
    private function goodsList($data)
    {

        // 商品列表获取条件
        $param = array_merge([
            'status' => 0,         // 商品状态默认上架
            'category_id' => 0,     // 分类id
            'search' => '',         // 搜索关键词
            'sharpGoodsIds' => [],         // ids
            'spec_type' => 0,         // ids
        ], $data);

        // 筛选条件
        $filter = [];
        $filter['is_delete'] = 0;
        $filter['wxapp_id'] = $param['wxapp_id'];
        $page = isset($param['page']) && is_numeric($param['page']) ? intval($param['page']) : 1;
        $limit = 10;
        $offset = ($page - 1) * $limit;
        $param['category_id'] > 0 && $filter['category_id'] = ['IN', Category::getSubCategoryId($param['category_id'])];
        !empty($param['sharpGoodsIds'])  && $filter['goods_id'] = ['NOT IN', $param['sharpGoodsIds']];
        $param['status'] > 0 && $filter['goods_status'] = $param['status'];
        !empty($param['search']) && $filter['goods_name'] = ['like', '%' . trim($param['search']) . '%'];
        $param['spec_type'] > 0 && $filter['spec_type'] = $param['spec_type'];
        // 多规格商品 最高价与最低价
        $GoodsSku = new GoodsSku;
        $minPriceSql = $GoodsSku->field(['MIN(goods_price)'])
            ->where('goods_id', 'EXP', "= `yoshop_goods`.`goods_id`")->buildSql();
        $maxPriceSql = $GoodsSku->field(['MAX(goods_price)'])
            ->where('goods_id', 'EXP', "= `yoshop_goods`.`goods_id`")->buildSql();
        // 执行查询
        $list = $this
            ->field(['*', '(sales_initial + sales_actual) as goods_sales',
                "$minPriceSql AS goods_min_price",
                "$maxPriceSql AS goods_max_price"
            ])
            ->with(['category', 'image.file', 'sku'])
            ->where($filter)
            ->order(['goods_sort', 'goods_id' => 'desc'])
            ->limit($offset, $limit)
            ->select();
        // 整理列表数据并返回
        return $this->setGoodsListData($list, true);

    }

    /**
     * 添加商品规格
     * @param $data
     * @param $isUpdate
     * @throws \Exception
     */
    private function addGoodsSpec($data, $isUpdate = false)
    {

        // 更新模式: 先删除所有规格
        $model = new GoodsSku;
        $isUpdate && $model->removeAll($this['goods_id']);
        $data['sku']['wxapp_id'] = self::$wxapp_id;
        // 添加规格数据
        if ($data['spec_type'] == '10') {
            // 单规格
            $this->sku()->save($data['sku']);
        } else if ($data['spec_type'] == '20') {
            // 添加商品与规格关系记录
            $model->addGoodsSpecRel($this['goods_id'], $data['spec_many']['spec_attr']);
            // 添加商品sku
            $model->addSkuList($this['goods_id'], $data['spec_many']['spec_list']);
        }
    }


    /**
     * 添加商品图片
     * @param $images
     * @return int
     * @throws \think\Exception
     * @throws \think\exception\PDOException
     */
    private function addGoodsImages($images)
    {
        $this->image()->delete();
        $data = array_map(function ($image_id) {
            return [
                'image_id' => $image_id,
                'wxapp_id' => self::$wxapp_id
            ];
        }, $images);
        return $this->image()->saveAll($data);
    }

    /**
     * 设置商品展示的数据
     * @param $data
     * @param bool $isMultiple
     * @param callable $callback
     * @return mixed
     */
    protected function setGoodsListData($data, $isMultiple = true, callable $callback = null)
    {
        if (!$isMultiple) $dataSource = [&$data]; else $dataSource = &$data;
        // 整理商品列表数据
        foreach ($dataSource as &$goods) {
            // 商品主图
            $goods['goods_image'] = $goods['image'][0]['file_path'];
            // 商品默认规格
            $goods['goods_sku'] = $goods['sku'][0];
            // 回调函数
            is_callable($callback) && call_user_func($callback, $goods);
        }
        return $data;
    }

    /**
     * 商品多规格信息
     * @param \think\Collection $specRel
     * @param \think\Collection $skuData
     * @return array
     */
    public function getManySpecData($specRel, $skuData)
    {
        // spec_attr
        $specAttrData = [];
        foreach ($specRel as $item) {
            if (!isset($specAttrData[$item['spec_id']])) {
                $specAttrData[$item['spec_id']] = [
                    'group_id' => $item['spec']['spec_id'],
                    'group_name' => $item['spec']['spec_name'],
                    'spec_items' => [],
                ];
            }
            $specAttrData[$item['spec_id']]['spec_items'][] = [
                'item_id' => $item['spec_value_id'],
                'spec_value' => $item['spec_value'],
            ];
        }

        // spec_list
        $specListData = [];
        foreach ($skuData as $item) {
            $image = (isset($item['image']) && !empty($item['image'])) ? $item['image'] : ['file_id' => 0, 'file_path' => ''];
            $specListData[] = [
                'goods_sku_id' => $item['goods_sku_id'],
                'spec_sku_id' => $item['spec_sku_id'],
                'rows' => [],
                'form' => [
                    'image_id' => $image['file_id'],
                    'image_path' => $image['file_path'],
                    'goods_no' => $item['goods_no'],
                    'goods_price' => $item['goods_price'],
                    'goods_weight' => $item['goods_weight'],
                    'line_price' => $item['line_price'],
                    'stock_num' => $item['stock_num'],
                ],
            ];
        }
        return ['spec_attr' => array_values($specAttrData), 'spec_list' => $specListData];
    }


    /**
     * 修改商品状态
     * @param $goods_id
     * @param $state
     * @return false|int
     */
    public function setStatus($param)
    {
        return $this->allowField(true)->save(
                ['goods_status' => $param['status']],
                ['goods_id'=>$param['goods_id']]) !== false;
    }

    /**
     * 删除商品
     * @param $goods_id
     * @param $state
     * @return false|int
     */
    public function goodsDel($param)
    {
        return $this->allowField(true)->save(
                ['is_delete' => 1],
                ['goods_id'=>$param['goods_id']]) !== false;
    }

    /**
     * 获取当前商品总数
     * @param array $where
     * @return int|string
     * @throws \think\Exception
     */
    public function getGoodsTotal($where = [])
    {
        return $this->where('is_delete', '=', 0)->where($where)->count();
    }


    /**
     * 计算显示销量 (初始销量 + 实际销量)
     * @param $value
     * @param $data
     * @return mixed
     */
    public function getGoodsSalesAttr($value, $data)
    {
        return $data['sales_initial'] + $data['sales_actual'];
    }

    /**
     * 获取器：单独设置折扣的配置
     * @param $json
     * @return mixed
     */
    public function getAloneGradeEquityAttr($json)
    {
        return json_decode($json, true);
    }

    /**
     * 修改器：单独设置折扣的配置
     * @param $data
     * @return mixed
     */
    public function setAloneGradeEquityAttr($data)
    {
        return json_encode($data);
    }

    /**
     * 关联商品分类表
     * @return \think\model\relation\BelongsTo
     */
    public function category()
    {
        return $this->belongsTo('Category');
    }

    /**
     * 关联商品规格表
     * @return \think\model\relation\HasMany
     */
    public function sku()
    {
        return $this->hasMany('GoodsSku')->order(['goods_sku_id' => 'asc']);
    }

    /**
     * 关联商品规格关系表
     * @return \think\model\relation\BelongsToMany
     */
    public function specRel()
    {
        return $this->belongsToMany('SpecValue', 'GoodsSpecRel')->order(['id' => 'asc']);
    }

    /**
     * 关联商品图片表
     * @return \think\model\relation\HasMany
     */
    public function image()
    {
        return $this->hasMany('GoodsImage')->order(['id' => 'asc']);
    }

    /**
     * 关联运费模板表
     * @return \think\model\relation\BelongsTo
     */
    public function delivery()
    {
        return $this->BelongsTo('Delivery');
    }

    /**
     * 关联订单评价表
     * @return \think\model\relation\HasMany
     */
    public function commentData()
    {
        return $this->hasMany('Comment');
    }

    /**
     * 计费方式
     * @param $value
     * @return mixed
     */
    public function getGoodsStatusAttr($value)
    {
        $status = [10 => '上架', 20 => '下架'];
        return ['text' => $status[$value], 'value' => $value];
    }






}
